﻿// Decompiled with JetBrains decompiler
// Type: Microsoft.InfoCards.ClientUIRequest
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// MVID: 8E14765A-6610-409A-BA36-099A0642905D
// Assembly location: E:\git\ALLIDA\windll\infocard.exe

using Microsoft.InfoCards.Diagnostics;
using System;
using System.Diagnostics;
using System.IO;
using System.Security.Principal;
using System.Threading;

namespace Microsoft.InfoCards
{
  internal abstract class ClientUIRequest : ClientRequest
  {
    private static object s_syncRoot = new object();
    private static ClientUIRequest.ProcessHandleDictionary s_connectedProcesses = new ClientUIRequest.ProcessHandleDictionary();
    private AccessibilityApplicationManager m_atManager = new AccessibilityApplicationManager();
    private ManualResetEvent m_uiAgentDone;
    private StoreConnection m_rootStoreReference;
    private volatile InfoCardUIAgent m_uiAgent;
    private InfoCardUIAgent.CallMode m_uiAgentMode;

    public ClientUIRequest(
      Process callingProcess,
      WindowsIdentity callingIdentity,
      InfoCardUIAgent uiAgent,
      IntPtr rpcHandle,
      Stream inArgs,
      Stream outArgs,
      InfoCardUIAgent.CallMode callMode,
      ExceptionList recoverableExceptions)
      : base(callingProcess, callingIdentity, rpcHandle, inArgs, outArgs, recoverableExceptions)
    {
      this.m_uiAgentMode = callMode;
      this.m_uiAgentDone = new ManualResetEvent(false);
      this.m_uiAgent = uiAgent;
      this.m_uiAgent.SetRequest(this);
    }

    public static int BindToService(IntPtr rpcHandle, out IntPtr context)
    {
      int num = 0;
      context = IntPtr.Zero;
      try
      {
        Process callingProcess = ClientRequest.GetCallingProcessFromRpcHandle(rpcHandle);
        WindowsImpersonationContext impersonationContext = NativeMcppMethods.CreateServiceExecutionIdentity(callingProcess).Impersonate();
        try
        {
          int key = 0;
          lock (ClientUIRequest.s_syncRoot)
          {
            try
            {
              try
              {
                key = ClientUIRequest.s_connectedProcesses.GetNewHandle();
              }
              catch (IndexOutOfRangeException ex)
              {
                throw InfoCardTrace.ThrowHelperError((Exception) new ServiceBusyException(SR.GetString("TooManyClientUIConnections"), (Exception) ex));
              }
              ClientUIRequest.s_connectedProcesses[key] = callingProcess;
              context = new IntPtr(key);
              key = 0;
              callingProcess = (Process) null;
            }
            finally
            {
              callingProcess?.Dispose();
              if (key != 0)
                ClientUIRequest.s_connectedProcesses.Remove(key);
            }
          }
        }
        finally
        {
          impersonationContext.Undo();
        }
      }
      catch (InfoCardBaseException ex)
      {
        num = ex.NativeHResult;
      }
      return num;
    }

    public static Process GetContextMapping(IntPtr context, bool clear)
    {
      int int32 = context.ToInt32();
      Process process = (Process) null;
      lock (ClientUIRequest.s_syncRoot)
      {
        if (ClientUIRequest.s_connectedProcesses.ContainsHandle(int32))
        {
          process = ClientUIRequest.s_connectedProcesses[int32];
          if (clear)
            ClientUIRequest.s_connectedProcesses.Remove(int32);
        }
      }
      return process;
    }

    public static void RemoveAndDisposeContextMapping(IntPtr context)
    {
      ClientUIRequest.GetContextMapping(context, true)?.Dispose();
    }

    public InfoCardUIAgent.CallMode UIAgentMode
    {
      get
      {
        return this.m_uiAgentMode;
      }
    }

    internal InfoCardUIAgent UIAgent
    {
      get
      {
        return this.m_uiAgent;
      }
    }

    public int UIAgentPid
    {
      get
      {
        return (int) this.UIAgent.ProcessId;
      }
    }

    public string UIAgentLogonSid
    {
      get
      {
        return this.UIAgent.TrustedUserSid;
      }
    }

    public bool UIAgentActive
    {
      get
      {
        if (this.UIAgent != null)
          return this.UIAgent.IsActive;
        return false;
      }
    }

    protected override void OnInitializeAsUser()
    {
      base.OnInitializeAsUser();
      this.m_rootStoreReference = StoreConnection.CreateConnection();
    }

    protected override void PreProcessRequest()
    {
      try
      {
        base.PreProcessRequest();
      }
      catch (UIAgentInitializationException ex)
      {
        throw;
      }
      catch (UserCancelledException ex)
      {
        throw;
      }
      catch (UntrustedRecipientException ex)
      {
        throw;
      }
      catch (UIAgentCrashedException ex)
      {
        throw new CommunicationException(SR.GetString("UIAgentCrash"));
      }
      catch (InfoCardBaseException ex)
      {
        throw this.ShowError((Exception) ex);
      }
    }

    protected override void ProcessRequest()
    {
      try
      {
        base.ProcessRequest();
      }
      catch (UntrustedRecipientException ex)
      {
        throw;
      }
      catch (UIAgentInitializationException ex)
      {
        throw;
      }
      catch (UserCancelledException ex)
      {
        throw;
      }
      catch (UIAgentCrashedException ex)
      {
        throw new CommunicationException(SR.GetString("UIAgentCrash"));
      }
      catch (InfoCardBaseException ex)
      {
        throw this.ShowError((Exception) ex);
      }
    }

    protected override void PostProcessRequest()
    {
      try
      {
        base.PostProcessRequest();
      }
      catch (InfoCardBaseException ex)
      {
        throw this.ShowError((Exception) ex);
      }
    }

    protected Exception ShowError(Exception ex)
    {
      if (this.m_uiAgent.IsShuttingDown)
        return ex;
      this.ProcessingException = ex;
      this.m_uiAgent.ResetUIResult();
      if (ClientUIRequest.RequestResult.Untrusted == this.m_uiAgent.ShowUI(InfoCardUIAgent.CallMode.Error))
        ex = InfoCardTrace.ThrowHelperError((Exception) new UntrustedRecipientException());
      this.ProcessingException = (Exception) null;
      return ex;
    }

    protected void StartAndWaitForUIAgent()
    {
      switch (this.m_uiAgent.ShowUI(this.UIAgentMode))
      {
        case ClientUIRequest.RequestResult.Ok:
          break;
        case ClientUIRequest.RequestResult.Cancel:
        case ClientUIRequest.RequestResult.Error:
          throw InfoCardTrace.ThrowHelperError((Exception) new UserCancelledException());
        case ClientUIRequest.RequestResult.Untrusted:
          throw InfoCardTrace.ThrowHelperError((Exception) new UntrustedRecipientException());
        case ClientUIRequest.RequestResult.UIFailedInitialization:
          throw InfoCardTrace.ThrowHelperError((Exception) new UIAgentInitializationException());
        case ClientUIRequest.RequestResult.UICrashed:
          throw InfoCardTrace.ThrowHelperError((Exception) new UIAgentCrashedException());
        default:
          InfoCardTrace.Assert(false, "We should never get Pending or invalid state here");
          break;
      }
    }

    public void StartAccessibilityApplications(uint userATApplicationFlags)
    {
      if (this.m_uiAgent == null)
        return;
      string trustedUserSid = this.m_uiAgent.TrustedUserSid;
      this.m_atManager.RestartOnInfoCardDesktop(userATApplicationFlags, this.m_uiAgent.TrustedUserToken, ref trustedUserSid, "WinSta0\\" + this.m_uiAgent.DesktopName, this.m_uiAgent.TsSessionId, this.CallerPid, this.RequestorIdentity);
    }

    public bool RestartAccessibilityApplications()
    {
      this.m_atManager.Stop();
      return this.m_atManager.RestartOnUsersDesktop(this.CallerPid, "WinSta0\\Default", this.RequestorIdentity);
    }

    public void StopAccessibilityApplications()
    {
      this.m_atManager.Stop();
    }

    public void UserCancel(bool untrusted)
    {
      lock (this.SyncRoot)
      {
        this.CancelServiceAsyncOperation(untrusted);
        this.OnUserCancel();
      }
    }

    protected virtual void OnUserCancel()
    {
    }

    private void ReleaseUIAgent()
    {
      lock (this.SyncRoot)
      {
        this.CheckIfAllAsyncOpsCompleted();
        this.StopAccessibilityApplications();
        if (this.m_uiAgent == null)
          return;
        this.m_uiAgent.ReleaseUI();
        this.m_uiAgent.ClearRequest(this);
        this.m_uiAgent = (InfoCardUIAgent) null;
      }
    }

    protected override void OnDisposeAsUser()
    {
      base.OnDisposeAsUser();
      if (this.m_rootStoreReference == null)
        return;
      this.m_rootStoreReference.Close();
      this.m_rootStoreReference = (StoreConnection) null;
    }

    protected override void OnDisposeAsSystem()
    {
      if (this.m_uiAgentDone != null)
      {
        this.m_uiAgentDone.Close();
        this.m_uiAgentDone = (ManualResetEvent) null;
      }
      ClientUIRequest.RemoveAndDisposeContextMapping(this.RpcHandle);
      this.ReleaseUIAgent();
      base.OnDisposeAsSystem();
    }

    private class ProcessHandleDictionary : HandleDictionary<Process>
    {
    }

    public enum RequestResult
    {
      Pending,
      Ok,
      Cancel,
      Untrusted,
      Error,
      UIFailedInitialization,
      UICrashed,
    }
  }
}
